const http = require('http')
const multiparty = require('multiparty');
const path = require("path");
const fs = require("fs");
const fse = require('fs-extra')

const server = http.createServer()
process.setMaxListeners(0)

server.on('request', async (request, res) => {
    res.setHeader('Access-Control-Allow-Origin', '*')
    res.setHeader('Access-Control-Allow-Headers', '*')

    if (request.url === '/upload') {
        const form = new multiparty.Form();
        form.parse(request, function(err, fields, files) {
            if (err) {
                return
            }
            const [file] = files.file
            const [fileName] = fields.fileName
            const [chunkName] = fields.chunkName
            const chunkDir = createDirAndWrite(`./${fileName}-chunks`)

            chunkDir(file, chunkName)

            res.writeHead(200, { 'Content-Type': 'application/json' });
            res.end(JSON.stringify({
                code: 200,
                message: 'success',
            }));
        });
    }

    if (request.url === '/merge') {
        /**
         * 接收传递过来的JSON参数，进行解析
         * 1. 根据传入的文件名 匹配对应的文件夹，并读取文件夹内所有的文件
         * 2. 将读取的文件进行排序，并转为读取流
         * 3. 读取流接着写入流，逐一合并成一个文件，并删除已读取过的文件，结束后删除chunks文件夹
         */
        const params = await resolvePost(request)
        mergeChunks(`./${params.fileName}-chunks`, params.fileName, params.size)
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({
            code: 200,
            message: 'success',
        }));
    }

});

function mergeChunks(chunkDir, fileName, size) {
    const chunkDirPath = path.resolve(__dirname, `./${chunkDir}`)
    fse.readdir(chunkDirPath).then(files => {
        const paths = files.sort((a, b) => {
            const aIndex = a.replace(`${fileName}-`, '')
            const bIndex = b.replace(`${fileName}-`, '')
            return aIndex - bIndex
        })

        const writeList = paths.map((filePath, index) => {
            const chunkPath = path.resolve(chunkDirPath, filePath)
            const writeStream = fs.createWriteStream(path.resolve(__dirname, './file/'+fileName), {
                start: index * size
            })
            return chunkReadStream(chunkPath, writeStream)
        })

        Promise.all(writeList).then(() => {
            fse.removeSync(chunkDirPath)
        })
    });
}

function chunkReadStream(chunkPath, writeStream) {
    return new Promise((resolve) => {
        const readStream = fs.createReadStream(chunkPath)
        readStream.on('end', () => {
            fs.rmSync(chunkPath)
            resolve()
        })
        readStream.pipe(writeStream)
    })
}


function createDirAndWrite(dirName) {
    const dirPath = path.resolve(__dirname, dirName)
    if (!fs.existsSync(dirPath)) {
        fs.mkdirSync(dirPath)
    }
    return function (file, chunkName) {
        fse.moveSync(file.path, `${dirPath}/${chunkName}`, { overwrite: true })
    }
}

// 解析POST请求传递的参数
function resolvePost(req) {
    // 解析参数
    return new Promise(resolve => {
        let chunk = ''
        req.on('data', data => { //req接收到了前端的数据
            chunk += data //将接收到的所有参数进行拼接
        })
        req.on('end', () => {
            resolve(JSON.parse(chunk))//将字符串转为JSON对象
        })
    })
}

server.listen(8000, () => {
    console.log('监听了8000端口')
});